namespace ClassyBlog.Infrastructure
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using DomainObjects;

    public class Renderer : IRenderer
    {
        public Renderer(
            IEnumerable<IFormatter> formatters, IMacroRunner macroRunner)
        {
            if (formatters == null)
            {
                throw new ArgumentNullException("formatters");
            }

            if (macroRunner == null)
            {
                throw new ArgumentNullException("macroRunner");
            }

            Formatters = formatters;
            MacroRunner = macroRunner;
        }

        protected IEnumerable<IFormatter> Formatters { get; private set; }

        protected IMacroRunner MacroRunner { get; private set; }

        public virtual string RenderFull(IContent content)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            var formatter = Formatters.FirstOrDefault(f =>
                f.Supports(content.Type));

            if (formatter == null)
            {
                throw new InvalidOperationException(
                    TextMessages.Renderer_RenderFull_Formatter_NotFound);
            }

            var formattedBody = formatter.Format(content.Body);
            var renderedBody = MacroRunner.Run(formattedBody);

            return renderedBody;
        }

        public virtual string RenderSummary(
            IContent content, string tagName = "p", int length = 240)
        {
            if (string.IsNullOrWhiteSpace(tagName))
            {
                throw new ArgumentException(
                    TextMessages.Renderer_RenderSummary_Tag_Name_Blank,
                    "tagName");
            }

            if (length <= 0)
            {
                throw new ArgumentException(
                    TextMessages.
                    Renderer_RenderSummary_Length_Positive_Integer,
                    "length");
            }

            var renderedBody = RenderFull(content);

            var summaryExpression = RegexExpressions.GetOrAddSummaryExpression(
                tagName, length);

            var match = summaryExpression.Match(renderedBody);

            return match.Success ? match.Value : null;
        }
    }
}